package jupitermouse.site.juc.demo.aqs.countdownlatch;

import java.util.concurrent.CountDownLatch;

/**
 * <p>
 * 计数后统一启动
 * 场景：
 * 1. 开关/哨子(初始count=1)：所有调用它的await()方法的线程都会等待，直到开关打开(执行一次countDown())。强调的是同时二字。
 * 强调的是同时二字。。加载缓存，启动时预热
 * 2. 计数器/总闸(初始count=n)：所有调用它的countDown()方法的线程都会使count减1，直到为0，释放所有线程。强调的是多个二字。
 * </p>
 *
 * @author jupiter
 */
public class CountDownLatchApp {

    static CountDownLatch countDownLatch = new CountDownLatch(3);

    static CountDownLatch latchSwitch = new CountDownLatch(1);

    public static void main(String[] args) {
//        countDownLatchCount();

        countDownLatchSwitch();
    }

    /**
     * 计数器功能
     */
    static void countDownLatchCount() {
        new Thread(()->{
            System.out.println("Thread1");
            countDownLatch.countDown(); // 3-1
            System.out.println("Thread1 end");
        }).start();

        new Thread(()->{
            System.out.println("Thread2");
            countDownLatch.countDown(); // 2-1
            System.out.println("Thread2 end");
        }).start();

        new Thread(()->{
            System.out.println("Thread3");
            countDownLatch.countDown(); // 1-1
            System.out.println("Thread3 end");
        }).start();

        try {
            // Thread 阻塞Thread.currentThread
            countDownLatch.await(); // 阻塞 直到 countdown n -> 0.
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("计数器完毕！");
    }

    /**
     * 模拟CountDownLatch的开关作用，此情景下可以用栅栏实现
     */
    static void countDownLatchSwitch() {

        for (int i = 0; i < 20; i++) {
            new Thread(() -> {
                try {
                    latchSwitch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程准备完成，ThreadName:" + Thread.currentThread().getName());
            }).start();
        }
        System.out.println("准备开始～～");
        latchSwitch.countDown();
    }

}
